#include "GLTwoShaderTriangleWindow.h"

GLTwoShaderTriangleWindow::GLTwoShaderTriangleWindow(QWidget* parent)
	: QOpenGLWidget(parent)
{
	this->resize(QSize(480, 480));
	this->setWindowTitle("使用两个Shader输出两个不同颜色的三角形");
	this->setWindowIcon(QIcon("images/opencv.png"));
}
void GLTwoShaderTriangleWindow::initializeGL() {
	initializeOpenGLFunctions();
	//清屏颜色
	glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
	glClear(GL_COLOR_BUFFER_BIT);
	qDebug() << "初始化成功";


	//包含：着色器创建、绑定、解绑、链接
	//programId1 = createAndLinkProgram(GL_VERTEX_SHADER, ":/QtForOpenCV4Tool/shader/two_triangle.vert"
	//	, GL_FRAGMENT_SHADER, ":/QtForOpenCV4Tool/shader/two_triangle.frag");
	//programId2 = createAndLinkProgram(GL_VERTEX_SHADER, ":/QtForOpenCV4Tool/shader/two_triangle.vert"
	//	, GL_FRAGMENT_SHADER, ":/QtForOpenCV4Tool/shader/two_triangle_yello.frag");
	buildShader();


	float firstTriangle[] = {
		-0.9f, -0.5f, 0.0f,  // left 
		-0.0f, -0.5f, 0.0f,  // right
		-0.45f, 0.5f, 0.0f,  // top 
	};
	float secondTriangle[] = {
		0.0f, -0.5f, 0.0f,  // left
		0.9f, -0.5f, 0.0f,  // right
		0.45f, 0.5f, 0.0f   // top 
	};
	//创建VAO、VBO
	glGenVertexArrays(2, VAOs);
	glGenBuffers(2, VBOs);
	//第一对VAO和VBO关联
	glBindVertexArray(VAOs[0]);
	glBindBuffer(GL_ARRAY_BUFFER, VBOs[0]);
	glBufferData(GL_ARRAY_BUFFER, sizeof(firstTriangle), firstTriangle, GL_STATIC_DRAW);//将数据传给VBO
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);//告知显卡顶点数组该如何解析
	glEnableVertexAttribArray(0);

	//第二对VAO和VBO关联
	glBindVertexArray(VAOs[1]);
	glBindBuffer(GL_ARRAY_BUFFER, VBOs[1]);
	glBufferData(GL_ARRAY_BUFFER, sizeof(secondTriangle), secondTriangle, GL_STATIC_DRAW);//将数据传给VBO
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);//告知显卡顶点数组该如何解析
	glEnableVertexAttribArray(0);


}
void GLTwoShaderTriangleWindow::buildShader() {
	//编译顶点着色器和片元着色器
	GLuint vertexShader = getShaderId(GL_VERTEX_SHADER, ":/QtForOpenCV4Tool/shader/two_triangle.vert");
	GLuint fragmentShader = getShaderId(GL_FRAGMENT_SHADER, ":/QtForOpenCV4Tool/shader/two_triangle.frag");
	GLuint fragmentShaderYello = getShaderId(GL_FRAGMENT_SHADER, ":/QtForOpenCV4Tool/shader/two_triangle_yello.frag");
	programId1 = glCreateProgram();
	programId2 = glCreateProgram();
	glAttachShader(programId1, vertexShader);
	glAttachShader(programId1, fragmentShader);
	glLinkProgram(programId1);
	getLinkProgramErrorInfo(programId1);

	glAttachShader(programId2, vertexShader);
	glAttachShader(programId2, fragmentShaderYello);
	glLinkProgram(programId2);
	getLinkProgramErrorInfo(programId2);

	glDeleteShader(vertexShader);
	glDeleteShader(fragmentShader);
	glDeleteShader(fragmentShaderYello);
}
void GLTwoShaderTriangleWindow::getLinkProgramErrorInfo(GLuint programId) {
	int success;
	char infoLog[512];
	glGetProgramiv(programId, GL_LINK_STATUS, &success);
	if (!success) {
		glGetProgramInfoLog(programId, 512, NULL, infoLog);
		qDebug() << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog;
	}
}
GLuint GLTwoShaderTriangleWindow::getShaderId(GLenum shaderType, QString resPath) {
	//创建顶点着色器
	unsigned int shaderId = glCreateShader(shaderType);
	QFile vertexShaderFile(resPath);
	if (!vertexShaderFile.open(QIODevice::ReadOnly)) {
		qDebug() << "Cannot open vertex shader file for reading";
	}
	QString verQStr = vertexShaderFile.readAll();
	std::string verStdStr = verQStr.toStdString();
	const char* vertexStr = verStdStr.c_str();
	qDebug() << "vertexStr-------------" << vertexStr;
	vertexShaderFile.flush();
	vertexShaderFile.close();
	glShaderSource(shaderId, 1, &vertexStr, NULL);
	glCompileShader(shaderId);
	getCompileShaderErrorInfo(shaderId);
	return shaderId;
}
void GLTwoShaderTriangleWindow::getCompileShaderErrorInfo(GLuint shaderId) {
	int success;
	char infoLog[512];
	glGetShaderiv(shaderId, GL_COMPILE_STATUS, &success);
	if (!success)
	{
		glGetShaderInfoLog(shaderId, 512, NULL, infoLog);
		qDebug() << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog;
	}
}
void GLTwoShaderTriangleWindow::resizeGL(int w, int h) {
	glViewport(0, 0, w, h);
}
void GLTwoShaderTriangleWindow::paintGL() {
	glUseProgram(programId1);
	glBindVertexArray(VAOs[0]);
	glDrawArrays(GL_TRIANGLES, 0, 3);

	glUseProgram(programId2);
	glBindVertexArray(VAOs[1]);
	glDrawArrays(GL_TRIANGLES, 0, 3);

}
GLTwoShaderTriangleWindow::~GLTwoShaderTriangleWindow()
{
	/*glDeleteVertexArrays(2, VAOs);
	glDeleteBuffers(2, VBOs);
	glDeleteProgram(programId1);
	glDeleteProgram(programId2);*/
}
